Analizie poddano dane pozyskane z 17 paneli fotowoltaicznych, znajdujących się w 14 lokalizacjach w 3 różnych elektrowniach we Włoszech. Dane gromadzone były od 2 stycznia 2012 roku do 31 grudnia 2013 roku w godzinach 2:00-20:00. Ze względu na pomiary parametrów środowiska takich jak np. wilgotność, temperatura, ciśnienie, nasłonecznienie itd. dokonywane przez czujniki, które mogą ulec awarii, w zbiorze występowały wartości zerowe. Wszystkie wartości atrybutów oprócz dat zostały znormalizowane. W zbiorze obok zmierzonych wartości znajdowały się współczynniki różnych parametrów, co wskazuje, że dane te już zostały częściowo przetworzone. Celem analizy jest wskazanie atrybutów najbardziej wpływających na liczbę kWh wyprodukowanej energii. W tym celu skorzystano z macierzy korelacji. Odkryto, że najsilniej skorelowane z produkowaną energią są stopień nasłonecznienia, wilgotność, wyliczony już w zbiorze współczynnik nasłonecznienia oraz niezidentyfikowany atrybut oryginalnego zbioru irr_pvgis_mod [mode], który prawdopodobnie także jest jakimś współczynnikiem wyliczonym na podstawie wartości nasłonecznienia. Biorąc pod uwagę, że wilgotność jest silnie ujemnie skorelowana z nasłonecznienie (im większe nasłonecznienie tym mniejsza wilgotność, im większa wilgotność tym mniejsze nasłonecznienie) stwierdzono, że największy wpływ na ilość wyprodukowanej energii ma nasłonecznienie, natomiast pozostałe parametry są mało istotne. Ciekawym faktem jest to, że według macierzy korelacji godzina oraz temperatura mają niewielki wpływ na nasłonecznienie. W przypadku godziny prawdopodobnie wynika to z faktu, że analizowane dane są z całego roku, a w zależności od pory roku w danej godzinie jest zupełnie inne nasłonecznienie. W przypadku temperatury może wynikać to z faktu, że nie mamy informacji, w którym miejscu znajdował się czujnik pomiarowy, czy był on na słońcu czy w cieniu. Przy konstrukcji modelu predykcji nie można pominąć wilgotności (choć jest silnie skorelowana z nasłonecznieniem), ponieważ czujniki dokonujące pomiaru wilgotności prawdopodobnie nigdy nie uległy awarii (brak wartości zerowych w zbiorze), w przeciwieństwie do czujników nasłonecznienia. Analizując wartości wyprodukowanej energii w czasie, możemy dostrzec, że część elektrowni miała w niektórych miesiącach wartość produkcji prawie na poziomie zerowym np. styczeń 2013 dla paneli o id: 0.05, 0.075, 0.025 oraz 0.425. Nie wiadomo czy taka sytuacja wynika z awarii czujników produkowanej energii czy częściowego wyłączenia panelu na ten okres. Do wykonania regresora wykorzystano atrybuty radiation, himidity, mode, radiation_param, altitude oraz place wraz z algorytmem Random Forest (ze względu na najniższy wynik metryki RMSE w stosunko do pozostałych badanych algorytmów). Dla algorytnu Random Forest przy wykorzystaniu biblioteki caret z parametrem ntree o wartości 30 uzyskano wartość metryki RMSE dla zbioru uczącego 0.07003180 oraz 0.06831101 dla zbioru testowego przy podziale zbioru w 75% na uczący oraz 25% na testowy.
library(dplyr)
library(ggplot2)
library('corrplot')
library(caret)
library(plotly)
library(tidyr)
all_data <- read.csv(file="elektrownie.csv", header=TRUE, sep=",")
Ze względu na wykorzystanie języka włoskiego do opisu kolumn lub nieintuicyjnych nazw zdecydowano się na zmianę nazw kolumn.
needed_data <- all_data
colnames(needed_data) <- c("measurementId", "place", "model", "brand", "latitude","longitude", "age", "year", "day", "hour", "date", "temperature", "radiation", "pressure", "windspeed", "humidity", "icon" , "dewpoint", "bearing", "cloudcover", "temp_param", "radiation_param", "pressure_param", "wind_param", "humidity_param", "dewpoint_param","bearing_param", "cloud_param", "distance", "altitude", "azimuth", "altitude_param", "azimuth_param","pcnm1", "pcnm2", "pcnm3", "pcnm4", "pcnm5", "pcnm6", "pcnm7", "pcnm8", "pcnm9", "pcnm10", "pcnm11", "pcnm12", "pcnm13", "pcnm14", "pcnm15", "mode", "mode_param","energy")
W celu łatwiejszego porównywania dat w poszczególnych wierszach (pomiarach) do zbioru dodano 4 kolumny: * only_month - kolumna typu numeric, zawiera informacje o miesiącu, wartości od 1 do 12, * only_day - kolumna typu numeric, zawiera informacje o dniu miesiąca, wartości od 1 do 31, * only_hour - kolumna typu numeric, zawiera informacje o godzinie (bez minut), wartości od 2 do 20, * date_posix - kolumna typu POSIXct, zawiera datę w formacie umożliwiiającym łatwe porównywanie dat. Dodatkowo dodano kolumne place_string zawierającą zagregowane informacje o lokalizacji danego panelu
needed_data$only_day <- as.numeric(format(as.POSIXct(factor(needed_data$date),format="%m/%d/%Y %H:%M"),"%d"))
needed_data$only_month <- as.numeric(format(as.POSIXct(factor(needed_data$date),format="%m/%d/%Y %H:%M"),"%m"))
needed_data$only_hour <- as.numeric(format(as.POSIXct(factor(needed_data$date),format="%m/%d/%Y %H:%M"),"%H"))
needed_data$date_posix <- as.POSIXct(as.character(needed_data$date), format="%m/%d/%Y %H:%M")
needed_data$place_string <- paste("Wsp: ", as.character(needed_data$latitude), " ",as.character(needed_data$longitude), " Panel: ", as.character(needed_data$place))
W zbiorze występują dane dla 17 różnych paneli słonecznych znajdujących się w 14 różnych lokalizacji w 3 różnych elektrowniach.
idbrands <- unique(needed_data$brand)
idbrands
## [1] 0.083 0.000 0.167 0.333 0.250 0.417
paste("Liczba unikalnych marek paneli: ", length(idbrands))
## [1] "Liczba unikalnych marek paneli: 6"
idbrands_with_models <- unique(needed_data[c("brand", "model")])
idbrands_with_models
## brand model
## 1 0.083 0.083
## 2 0.083 0.208
## 3 0.000 0.375
## 4 0.167 0.292
## 5 0.333 0.000
## 6 0.000 0.417
## 7 0.000 0.458
## 8 0.167 0.167
## 11 0.250 0.250
## 14 0.417 0.125
## 15 0.333 0.750
paste("Liczba unikalnych modeli paneli: ", length(idbrands_with_models))
## [1] "Liczba unikalnych modeli paneli: 2"
idplaces <- unique(needed_data$place)
idplaces
## [1] 0.425 0.250 0.350 0.325 0.000 0.375 0.400 0.125 0.225 0.075 0.300
## [12] 0.150 0.200 0.050 0.025 0.275 0.100
paste("Liczba paneli: ", length(idplaces))
## [1] "Liczba paneli: 17"
gps <- unique(needed_data[c("latitude", "longitude")])
gps
## latitude longitude
## 1 0.437 0.631
## 2 0.437 0.620
## 3 0.439 0.626
## 4 0.440 0.612
## 5 0.436 0.626
## 6 0.552 0.154
## 7 0.553 0.160
## 8 0.415 0.691
## 10 0.437 0.624
## 11 0.440 0.585
## 12 0.438 0.630
## 13 0.436 0.625
## 14 0.437 0.622
## 17 0.434 0.630
paste("Liczba unikalnych lokalizacji: ", length(gps))
## [1] "Liczba unikalnych lokalizacji: 2"
gps_with_places_id <- unique(needed_data[c("latitude", "longitude", "place")])
gps_with_places_id
## latitude longitude place
## 1 0.437 0.631 0.425
## 2 0.437 0.620 0.250
## 3 0.439 0.626 0.350
## 4 0.440 0.612 0.325
## 5 0.436 0.626 0.000
## 6 0.552 0.154 0.375
## 7 0.553 0.160 0.400
## 8 0.415 0.691 0.125
## 9 0.437 0.620 0.225
## 10 0.437 0.624 0.075
## 11 0.440 0.585 0.300
## 12 0.438 0.630 0.150
## 13 0.436 0.625 0.200
## 14 0.437 0.622 0.050
## 15 0.437 0.631 0.025
## 16 0.437 0.622 0.275
## 17 0.434 0.630 0.100
Przed dokonaniem wyliczenia wartości pustych warto zauważyć, że w zbiorze występuje 78521 wierszy, które posiadają wyprodukowaną energię na poziomie 0, 78489 wierszy, które posiadają zmierzony poziom nasłonecznienia na poziomie 0 oraz 72864 wierszy, które posiadają obie wspomniane wartości na poziomie 0. Kierując się tymi obserwacjami, możemy dostrzec, że w przypadku prawie 6 tys. wierszy, które mają nasłonecznienie na poziomie 0 oraz energie większą niż 0 mogła nastąpić awaria czujnika nasłonecznienia, natomiast w przypadku wierszy, które mają nasłonecznienie większe od 0, a wyprodukowaną energię na poziomie 0, elektrownia mogła zostać wyłączona (czujnik dokonywał ciągle pomiarów parametrów środowiska) lub niepoprawnie zapisano liczbę kwh wyprodukowanej energii.
Ze względu na to, że w zbiorze występują dla ciśnienia (pressure) tylko wartości zerowe lub większe niż 0.7, uznano, że zerowe wartości są wynikiem awarii czujników i zastąpiono je średnią niezerowych wartości ciśnienia dla określonego panelu.
for(idplace in idplaces) {
average_value <- mean(needed_data$pressure[needed_data$pressure > 0 & needed_data$place == idplace])
if(!is.na(average_value)) {
needed_data$pressure[needed_data$pressure == 0 & needed_data$place == idplace] <- average_value
}
}
Założono, że w nocy nasłonecznienie wynosi 0 (co wynika również z analizy pozyskanych danych), stąd zastapiono tylko wartości zerowe dla nasłonecznienia (radiation) z przediału godzinnego <5;20> oraz wyprodukowaną energią większą niż 0. Wartości zerowe zastąpiono średnią wartościa parametru dla danego czujnika w danym miesiącu o danej godzinie.
empty_values <- needed_data %>% filter(radiation == 0 & only_hour > 4 & only_hour < 20 & energy > 0)
not_empty_values <- needed_data %>% filter(radiation > 0 & only_hour > 4 & only_hour < 20)
for(idplace in idplaces) {
empty_radiation <- empty_values %>% filter(place == idplace)
if(nrow(empty_radiation) > 0) {
for(i in 1:nrow(empty_radiation)) {
row <- empty_radiation[i, ]
cloudcover_low <- row$cloudcover - 0.2
cloudcover_up <- row$cloudcover + 0.2
radiation_column <- not_empty_values %>% filter(place == idplace & only_hour == row$only_hour & only_month == row$only_month & cloudcover > cloudcover_low & cloudcover < cloudcover_up) %>% select(radiation)
if(nrow(radiation_column) > 0) {
average_value <- mean(radiation_column$radiation)
if(!is.na(average_value)) {
needed_data$radiation[which(needed_data$measurementId == row$measurementId)] <- average_value
}
}
}
}
}
Wszystkie wartości w zbiorze oprócz daty wykonania pomiaru zostały znormalizowane. Parametry możemy podzielić na niedyskretne (ze względu na nieznajomość dokładności pomiarów w określonym zakresie działania, np. temperatura przed dokonaniem normalizacji wartości, mogła być mierzona z różną dokładnością w zakresie [x;y]) oraz dyskretne (określony zbiór wartości, np. id panelu). Stąd statystyki danego parametru przedstawiono w zależności od jego typu.
## [1] "Rozmiar zbioru: 235790"
| Średnia | Wartość minimalna | Wartość maksymalna | Odchylenie standardowe | Liczba zerowych wartości | 1. kwartyl | 2. kwartyl | 3. kwartyl | |
|---|---|---|---|---|---|---|---|---|
| age | 0.3144706 | 0.000 | 1.000 | 0.3779699 | 69350 | 0.0000000 | 0.1250000 | 0.719000 |
| temperature | 0.3734429 | 0.045 | 0.818 | 0.1722182 | 0 | 0.2120000 | 0.3480000 | 0.530000 |
| radiation | 0.1111735 | 0.000 | 0.710 | 0.1343706 | 73949 | 0.0000000 | 0.0400000 | 0.208000 |
| pressure | 0.7529589 | 0.730 | 0.769 | 0.0044807 | 0 | 0.7510000 | 0.7530000 | 0.755000 |
| windspeed | 0.0762241 | 0.000 | 0.696 | 0.0501477 | 1070 | 0.0420000 | 0.0660000 | 0.102000 |
| humidity | 0.6843925 | 0.160 | 1.000 | 0.1817457 | 0 | 0.5400000 | 0.7000000 | 0.840000 |
| dewpoint | 0.6055304 | 0.139 | 0.865 | 0.0956441 | 0 | 0.5350000 | 0.6190000 | 0.683000 |
| bearing | 0.4512351 | 0.000 | 0.769 | 0.2303888 | 2520 | 0.3000000 | 0.4780000 | 0.660000 |
| cloudcover | 0.3590429 | 0.000 | 1.000 | 0.2595479 | 38394 | 0.2300000 | 0.3100000 | 0.510000 |
| temp_param | 0.1224742 | 0.009 | 0.983 | 0.0631091 | 0 | 0.0730000 | 0.1110000 | 0.126000 |
| radiation_param | 0.2220020 | 0.108 | 1.000 | 0.0115436 | 0 | 0.2160000 | 0.2200000 | 0.222000 |
| pressure_param | 0.0002370 | 0.000 | 1.000 | 0.0039993 | 233263 | 0.0000000 | 0.0000000 | 0.000000 |
| wind_param | 0.0385247 | 0.000 | 1.000 | 0.0048811 | 2 | 0.0370000 | 0.0380000 | 0.039000 |
| humidity_param | 0.0638395 | 0.034 | 0.579 | 0.0420096 | 0 | 0.0440000 | 0.0440000 | 0.062000 |
| dewpoint_param | 0.1193809 | 0.063 | 0.415 | 0.0133907 | 0 | 0.1140000 | 0.1140000 | 0.118000 |
| bearing_param | 0.3454981 | 0.000 | 1.000 | 0.0340350 | 1 | 0.3360000 | 0.3360000 | 0.339000 |
| cloud_param | 0.2061627 | 0.000 | 1.000 | 0.0300724 | 1 | 0.1960000 | 0.1960000 | 0.198000 |
| distance | 0.4686464 | 0.000 | 1.000 | 0.2967915 | 570 | 0.1912568 | 0.4590164 | 0.726776 |
| altitude | 0.5463627 | 0.111 | 0.884 | 0.1806407 | 0 | 0.4190000 | 0.5640000 | 0.681000 |
| azimuth | 0.4545834 | 0.128 | 0.818 | 0.1965414 | 0 | 0.2950000 | 0.4250000 | 0.635000 |
| altitude_param | 0.2055096 | 0.000 | 0.982 | 0.1494217 | 1 | 0.0960000 | 0.1360000 | 0.266000 |
| azimuth_param | 0.3652845 | 0.000 | 1.000 | 0.1822820 | 1 | 0.2090000 | 0.2880000 | 0.482000 |
| pcnm1 | 0.4223529 | 0.000 | 1.000 | 0.2043798 | 13870 | 0.3770000 | 0.3780000 | 0.380000 |
| pcnm2 | 0.3537647 | 0.000 | 0.972 | 0.2142737 | 13870 | 0.2500000 | 0.3770000 | 0.422000 |
| pcnm3 | 0.6044706 | 0.000 | 1.000 | 0.2170462 | 13870 | 0.5510000 | 0.6050000 | 0.730000 |
| pcnm4 | 0.5189412 | 0.000 | 1.000 | 0.2555701 | 13870 | 0.3630000 | 0.5310000 | 0.634000 |
| pcnm5 | 0.4164706 | 0.000 | 1.000 | 0.2502325 | 13870 | 0.3310000 | 0.4270000 | 0.462000 |
| pcnm6 | 0.4940588 | 0.000 | 1.000 | 0.2392556 | 13870 | 0.3390000 | 0.4930000 | 0.493000 |
| pcnm7 | 0.1141765 | 0.000 | 1.000 | 0.2249332 | 13870 | 0.0310000 | 0.0520000 | 0.114000 |
| pcnm8 | 0.4033529 | 0.000 | 1.000 | 0.2636083 | 13870 | 0.2040000 | 0.4120000 | 0.511000 |
| pcnm9 | 0.5371176 | 0.000 | 1.000 | 0.2616246 | 13870 | 0.5270000 | 0.5320000 | 0.600000 |
| pcnm10 | 0.6276471 | 0.000 | 1.000 | 0.2123752 | 13870 | 0.5530000 | 0.6190000 | 0.717000 |
| pcnm11 | 0.3236471 | 0.000 | 1.000 | 0.2066428 | 13870 | 0.2570000 | 0.3270000 | 0.327000 |
| pcnm12 | 0.7567647 | 0.000 | 1.000 | 0.2289319 | 13870 | 0.7480000 | 0.7600000 | 0.884000 |
| pcnm13 | 0.6500588 | 0.137 | 1.000 | 0.1995126 | 0 | 0.6140000 | 0.6140000 | 0.738000 |
| pcnm14 | 0.4892941 | 0.000 | 1.000 | 0.1838311 | 13870 | 0.4320000 | 0.4730000 | 0.530000 |
| pcnm15 | 0.5709412 | 0.000 | 1.000 | 0.2046190 | 13870 | 0.6120000 | 0.6140000 | 0.615000 |
| mode | 0.1767311 | 0.000 | 1.000 | 0.2210455 | 94008 | 0.0000000 | 0.0560000 | 0.325000 |
| mode_param | 0.1967021 | -0.025 | 1.006 | 0.0534842 | 2 | 0.1580000 | 0.1940000 | 0.213000 |
| energy | 0.1687714 | 0.000 | 1.000 | 0.2106090 | 78521 | 0.0000000 | 0.0490000 | 0.332000 |
| Wartość minimalna | Wartość maksymalna | Liczba unikalnych wartości | |
|---|---|---|---|
| place | 0.000 | 0.425 | 17 |
| brand | 0.000 | 0.417 | 6 |
| latitude | 0.415 | 0.553 | 9 |
| longitude | 0.154 | 0.691 | 12 |
| day | 0.000 | 1.000 | 365 |
| hour | 0.000 | 1.000 | 19 |
| measurementId | 1.000 | 276488.000 | 235790 |
| model | 0.000 | 0.750 | 11 |
| year | 2012.000 | 2013.000 | 2 |
| icon | 0.000 | 0.750 | 7 |
W tej sekcji zostały przedstawione rozkłady wartości wybranych atrybutów niedyskretnych.